package com.gzhryc.shared_device.oem.micro.api.controllers.xcx.v1.bxscn;

import java.io.IOException;
import java.text.ParseException;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;

import com.alipay.api.response.AlipayTradeCreateResponse;
import com.gzhryc.common.DateTools;
import com.gzhryc.common.MatrixToImageWriter;
import com.gzhryc.common.StringTools;
import com.gzhryc.common.config.PropertyTools;
import com.gzhryc.common.json.JsonTools;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.pay.adaptation.alipay.AlipayNormalPayService;
import com.gzhryc.pay.adaptation.weixin.WXPayNormalPayService;
import com.gzhryc.pay.adaptation.weixin.msg.normal.WXPayNormalPayResponse;
import com.gzhryc.servlet.WebUtils;
import com.gzhryc.servlet.annotation.Route;
import com.gzhryc.shared_device.base.enums.EOperatorType;
import com.gzhryc.shared_device.base.enums.EPayState;
import com.gzhryc.shared_device.base.enums.EPayType;
import com.gzhryc.shared_device.base.models.OperateInfo;
import com.gzhryc.shared_device.bxscn.code.dao.db.BXSCNShopOrder;
import com.gzhryc.shared_device.bxscn.code.dao.enums.BXSCNShopOrderEnum;
import com.gzhryc.shared_device.bxscn.code.services.BXSCNShopOrderService;
import com.gzhryc.shared_device.bxscn.code.services.PortableEnergyBatteryService;
import com.gzhryc.shared_device.common.payment.dao.db.AlipayOrder;
import com.gzhryc.shared_device.common.payment.dao.db.WXPayOrder;
import com.gzhryc.shared_device.common.payment.services.AlipayOrderService;
import com.gzhryc.shared_device.common.payment.services.WXPayOrderService;
import com.gzhryc.shared_device.oem.code.PayServiceFactory;
import com.gzhryc.shared_device.oem.code.business.EBusinessType;
import com.gzhryc.shared_device.oem.code.config.dao.enums.EAgreementCode;
import com.gzhryc.shared_device.oem.code.member.EMemberBusinessType;
import com.gzhryc.shared_device.oem.code.member.LoginMember;
import com.gzhryc.shared_device.oem.code.member.services.MemberAgreementService;
import com.gzhryc.shared_device.oem.code.order.CacheOrderCollect;
import com.gzhryc.shared_device.oem.code.place.dao.db.PlaceFreeMember;
import com.gzhryc.shared_device.oem.code.place.dao.db.PlacePhysicalStore;
import com.gzhryc.shared_device.oem.code.place.services.PlaceFreeMemberService;
import com.gzhryc.shared_device.oem.code.place.services.PlacePhysicalStoreService;
import com.gzhryc.shared_device.oem.micro.api.BXSCNShopLeaseConfig;
import com.gzhryc.shared_device.oem.micro.api.MicroConstants;
import com.gzhryc.shared_device.oem.micro.api.OrderCollectManager;
import com.gzhryc.shared_device.oem.micro.api.dto.xcx.ClientAPICodeConstants;
import com.gzhryc.shared_device.oem.micro.api.dto.xcx.PayResultCode;
import com.gzhryc.shared_device.oem.micro.api.dto.xcx.v1.bxscn.BXSCNShopLeasePayRequest;
import com.gzhryc.shared_device.oem.micro.api.dto.xcx.v1.bxscn.BXSCNShopLeasePayResponse;
import com.gzhryc.shared_device.oem.micro.api.dto.xcx.v1.bxscn.BXSCNShopPayResultRequest;
import com.gzhryc.shared_device.oem.micro.api.dto.xcx.v1.bxscn.BXSCNShopPayResultResponse;

public class BXSCNShopPayController {

    static Logger log = Logger.getLogger(BXSCNShopPayController.class);

    @Route(value = {"/xcx/v1/bxscn/shop/lease/pay.do"}, method = "POST")
    public BXSCNShopLeasePayResponse leasePay(HttpServletRequest request, HttpServletResponse response) {
        BXSCNShopLeasePayResponse apiResp = new BXSCNShopLeasePayResponse(ClientAPICodeConstants.EXECUTE_ERROR, "支付失败，请稍后再试");
        try {
            BXSCNShopLeasePayRequest apiReq = WebUtils.getJsonRequest(request, BXSCNShopLeasePayRequest.class);
            if (apiReq != null && apiReq.getBody().getPlaceId() != null && StringTools.isNotBlank(apiReq.getBody().getBatteryType())
                    && apiReq.getBody().getLeaseType() != null && apiReq.getBody().getLeaseDay() != null) {
                Integer payType = apiReq.getBody().getPayType() == null ? EPayType.WXPay.index() : apiReq.getBody().getPayType();
                Integer leaseType = apiReq.getBody().getLeaseType() == null?BXSCNShopOrderEnum.LeaseType.Unknown.index():apiReq.getBody().getLeaseType();
                Date leaseStartDate = null;
                Integer appointmentTime = null;
                if(StringTools.isNotBlank(apiReq.getBody().getLeaseStartDate())){
                	String appointmentTimeStr = apiReq.getBody().getAppointmentTime();
                	if(appointmentTimeStr == null){
                        //当前时间
                        appointmentTimeStr = DateFormatUtils.format(new Date(),"HH:mm");
                    }else {
                    	appointmentTime = DateTools.changeHHmm(appointmentTimeStr);
                    }
                    try {
                        leaseStartDate = DateUtils.parseDate(apiReq.getBody().getLeaseStartDate() + " " + appointmentTimeStr, "yyyy-MM-dd HH:mm");
                    }catch (ParseException e){
                        log.error(e.getMessage(),e);
                        apiResp.setMsg("起租日期格式不正确");
                        return apiResp;
                    }

                    //检查租借时间
                    Integer day = DateTools.differenceDay(new Date(),leaseStartDate);
                    if(day < 0 || day > 7){
                        apiResp.setMsg("起租时间只能提前7天");
                        return apiResp;
                    }
                }else {
                    apiResp.setMsg("请填写起租日期");
                    return apiResp;
                }
                
                if (EPayType.WXPay.index().equals(payType) || EPayType.Alipay.index().equals(payType)) {
                    if (StringTools.isBlank(apiReq.getBody().getAppId())) {
                        apiResp.setMsg("无效的应用ID");
                        return apiResp;
                    }
                }

                LoginMember loginMember = WebUtils.getAttribute(request, MicroConstants.ATTR_LOGIN_MEMBER, LoginMember.class);

                PlacePhysicalStore physicalStore = PlacePhysicalStoreService.self().getById(apiReq.getBody().getPlaceId());
                if (physicalStore == null) {
                    apiResp.setMsg("未找到网点信息");
                    return apiResp;
                }

                Long deviceCount = PortableEnergyBatteryService.self().countChargingByPlaceIdAndBatteryType(physicalStore.getId(),apiReq.getBody().getBatteryType());
                if (deviceCount == null || deviceCount <= 0) {
                    apiResp.setMsg("未找到可租借的设备");
                    return apiResp;
                }
 
                BXSCNShopLeaseConfig bxscnShopLeaseConfig = new BXSCNShopLeaseConfig();
                bxscnShopLeaseConfig.setLeaseDay(apiReq.getBody().getLeaseDay());
                bxscnShopLeaseConfig.setLeaseStartDate(leaseStartDate);
                bxscnShopLeaseConfig.setLeaseType(leaseType);
                bxscnShopLeaseConfig.setBatteryType(apiReq.getBody().getBatteryType());
                
                //白名单检查，未激活白名单不使用
                PlaceFreeMember freeMember = PlaceFreeMemberService.self().getByKeys(physicalStore.getId(), loginMember.getPhone());
                if(freeMember != null && freeMember.getMemberId() != null) {
                	bxscnShopLeaseConfig.setMemberType(EMemberBusinessType.FreeMember.index());
                }
                
                if(appointmentTime != null && physicalStore.getCloseTime() != null && physicalStore.getOpenTime() != null){
                    if(appointmentTime > physicalStore.getCloseTime() || appointmentTime < physicalStore.getOpenTime()){
                        apiResp.setMsg("请预约在网点营业时间："+physicalStore.getBusinessTimeStr() + "内");
                        return apiResp;
                    }
                }
                
                //同意协议
                if (StringTools.isNotBlank(apiReq.getBody().getAppId())) {
                	MemberAgreementService.self().signing(loginMember.getId(), EAgreementCode.RentAgreement.name(), apiReq.getBody().getAppId());
                }
                
                OperateInfo operateInfo = new OperateInfo(MicroConstants.PROGRAM_TYPE, MicroConstants.PROGRAM_TYPE_NAME);
                operateInfo.setOperator(EOperatorType.Member.index(), loginMember.getFullName());
                operateInfo.setOperateNote("租借便携式储能电池");

                if (EPayType.WXPay.index().equals(payType)) {
                    WXPayNormalPayService payService = PayServiceFactory.self().getWXPayNormalPayService(apiReq.getBody().getAppId(),
                            EBusinessType.BXSCN_SHOP.index());
                    if (payService == null) {
                        apiResp.setMsg("未配置应用微信支付服务");
                        return apiResp;
                    }

                    CacheOrderCollect orderCollect = OrderCollectManager.buildBXSCNShopCacheOrderCollect(loginMember, physicalStore, bxscnShopLeaseConfig
                            , payService.getConfig(), operateInfo);
                    if (orderCollect == null) {
                        apiResp.setMsg("创建订单失败，请稍后再试");
                        return apiResp;
                    }

                    WXPayNormalPayResponse externalResult = payService.applyPayOrder(orderCollect.getPayOrder());
                    if (externalResult != null) {
                        if(StringTools.isNotBlank(externalResult.getPrepay_id())) {
                            String payInfo = payService.buildXCXData(externalResult.getPrepay_id());
                            if (StringTools.isNotBlank(payInfo)) {
                                OrderCollectManager.saveWXPayOrderExternalContent(orderCollect.getPayOrder().getTradeNo(), JsonTools.toJson(externalResult));
                                log.info("微信支付返回：" + payInfo);
                                apiResp.setCode(ClientAPICodeConstants.SUCCESS, null);
                                apiResp.getBody().setTradeNo(orderCollect.getPayOrder().getTradeNo());
                                apiResp.getBody().setPayType(payType);
                                apiResp.getBody().setPayInfo(payInfo);
                            }
                        }else {
                            log.error("微信支付返回错误，返回信息：{{0:json}}", externalResult);
                        }
                    } else {
                        log.error("微信支付无返回，订单信息：{{0:json}}", orderCollect);
                    }
                }else if(EPayType.Alipay.index().equals(payType)) {
                	AlipayNormalPayService payService = PayServiceFactory.self().getAlipayNormalPayService(apiReq.getBody().getAppId(),
                            EBusinessType.BXSCN_SHOP.index());
                    if (payService == null) {
                        apiResp.setMsg("未配置应用支付宝支付服务");
                        return apiResp;
                    }
                    
                    CacheOrderCollect orderCollect = OrderCollectManager.buildBXSCNShopCacheOrderCollect(loginMember, physicalStore, bxscnShopLeaseConfig
                            , payService.getConfig(), operateInfo);
                    if (orderCollect == null) {
                        apiResp.setMsg("创建订单失败，请稍后再试");
                        return apiResp;
                    }
                    
                    AlipayTradeCreateResponse externalResult = payService.applyPayOrder(orderCollect.getAlipayOrder());
                    if (externalResult != null) {
                        if(StringTools.isNotBlank(externalResult.getOutTradeNo())) {
                        	OrderCollectManager.saveAlipayOrderExternalContent(orderCollect.getAlipayOrder().getTradeNo(), JsonTools.toJson(externalResult));
                            apiResp.setCode(ClientAPICodeConstants.SUCCESS, null);
                            apiResp.getBody().setTradeNo(externalResult.getTradeNo());
                            apiResp.getBody().setPayType(payType);
                        }else {
                            log.error("支付宝支付返回错误，返回信息：{{0:json}}", externalResult);
                        }
                    } else {
                        log.error("支付宝支付无返回，订单信息：{{0:json}}", orderCollect);
                    }
                }else if(EPayType.EWallet.index().equals(payType)){
                    CacheOrderCollect orderCollect = OrderCollectManager.buildBXSCNShopCacheOrderCollect(loginMember, physicalStore, bxscnShopLeaseConfig,operateInfo);
                    if (orderCollect == null) {
                        apiResp.setMsg("创建订单失败，请稍后再试");
                        return apiResp;
                    }

                    apiResp.setCode(ClientAPICodeConstants.SUCCESS, null);
                    apiResp.getBody().setTradeNo(orderCollect.getBxscnShopOrder().getTradeNo());
                    apiResp.getBody().setPayType(payType);
                }
            }
        } catch (Exception e) {
            log.error("创建订单失败，" + e.getMessage(), e);
        }
        return apiResp;
    }

    @Route(value = {"/xcx/v1/bxscn/shop/pay/result.do"}, method = "POST")
    public BXSCNShopPayResultResponse payResult(HttpServletRequest request){
        BXSCNShopPayResultResponse apiResp = new BXSCNShopPayResultResponse(ClientAPICodeConstants.NULL_DATA, "未找到支付结果");
        try {
            BXSCNShopPayResultRequest apiReq = WebUtils.getJsonRequest(request, BXSCNShopPayResultRequest.class);
            if (apiReq != null && apiReq.getBody().getPayType() != null && StringTools.isNotBlank(apiReq.getBody().getTradeNo())) {
                if(EPayType.WXPay.index().equals(apiReq.getBody().getPayType())){
                    Date createDate = new Date();
                    WXPayOrder payOrder = WXPayOrderService.self(createDate).getByTradeNo(apiReq.getBody().getTradeNo());
                    if (payOrder != null) {
                        apiResp.setCode(ClientAPICodeConstants.SUCCESS, null);
                        apiResp.getBody().setResultCode(PayResultCode.WAIT);
                        if (EPayState.Success.index().equals(payOrder.getPayStatus())) {
                            BXSCNShopOrder deviceOrder = BXSCNShopOrderService.self(new Date()).getByTradeNo(payOrder.getBusinessTradeNo());
                            if (deviceOrder != null) {
                                if (BXSCNShopOrderEnum.PayState.DepositSuccess.index().equals(deviceOrder.getPayState())) {
                                    apiResp.getBody().setResultCode(PayResultCode.SUCCESS);
                                }else if(BXSCNShopOrderEnum.PayState.Cancel.index().equals(deviceOrder.getState())){
                                    apiResp.getBody().setResultCode(PayResultCode.FAIL);
                                }
                            } else {
                                log.error("未找到设备订单，支付订单号：{{0}}，业务订单号：{{1}}", payOrder.getTradeNo(), payOrder.getBusinessTradeNo());
                            }
                        }
                    }
                }else if(EPayType.Alipay.index().equals(apiReq.getBody().getPayType())){
                    Date createDate = new Date();
                    AlipayOrder payOrder = AlipayOrderService.self(createDate).getByTradeNo(apiReq.getBody().getTradeNo());
                    if (payOrder != null) {
                        apiResp.setCode(ClientAPICodeConstants.SUCCESS, null);
                        apiResp.getBody().setResultCode(PayResultCode.WAIT);
                        if (EPayState.Success.index().equals(payOrder.getPayStatus())) {
                            BXSCNShopOrder deviceOrder = BXSCNShopOrderService.self(new Date()).getByTradeNo(payOrder.getBusinessTradeNo());
                            if (deviceOrder != null) {
                                if (BXSCNShopOrderEnum.PayState.DepositSuccess.index().equals(deviceOrder.getPayState())) {
                                    apiResp.getBody().setResultCode(PayResultCode.SUCCESS);
                                }else if(BXSCNShopOrderEnum.PayState.Cancel.index().equals(deviceOrder.getState())){
                                    apiResp.getBody().setResultCode(PayResultCode.FAIL);
                                }
                            } else {
                                log.error("未找到设备订单，支付订单号：{{0}}，业务订单号：{{1}}", payOrder.getTradeNo(), payOrder.getBusinessTradeNo());
                            }
                        }
                    }
                }else if(EPayType.EWallet.index().equals(apiReq.getBody().getPayType())){
                    BXSCNShopOrder deviceOrder = BXSCNShopOrderService.self(new Date()).getByTradeNo(apiReq.getBody().getTradeNo());
                    if (deviceOrder != null) {
                        apiResp.setCode(ClientAPICodeConstants.SUCCESS, null);
                        apiResp.getBody().setResultCode(PayResultCode.WAIT);
                        if (BXSCNShopOrderEnum.PayState.DepositSuccess.index().equals(deviceOrder.getPayState())) {
                            apiResp.getBody().setResultCode(PayResultCode.SUCCESS);
                        }else if(BXSCNShopOrderEnum.PayState.Cancel.index().equals(deviceOrder.getState())){
                            apiResp.getBody().setResultCode(PayResultCode.FAIL);
                        }
                    } else {
                        log.error("未找到设备订单，支付类型：{{0}}，业务订单号：{{1}}", EPayType.EWallet.note(), apiReq.getBody().getTradeNo());
                    }
                }
            }
        } catch (Exception e) {
            log.error("获取订单结果失败，" + e.getMessage(), e);
        }
        return apiResp;
    }

    @Route(value = { "/xcx/v1/bxscn/shop/order/qrcode.jpg" })
    public void qrcodeImg(HttpServletRequest request, HttpServletResponse response) {
        String tradeNo = WebUtils.getString(request, "tradeNo");
        if (StringUtils.isNotBlank(tradeNo)) {
            BXSCNShopOrder shopOrder = BXSCNShopOrderService.self(new Date()).getByTradeNo(tradeNo);
            if (shopOrder != null) {
                try {
                    String httpDomain = PropertyTools.get().getString("httpDomain");
                    String url = httpDomain + "/bxscn/shop/order/" + shopOrder.getTradeNo();
                    WebUtils.exportJPEG(response);
                    MatrixToImageWriter.writeToStream(url, 400, 300, "jpeg", response.getOutputStream());
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
        }
    }
}
